/* eslint-env node */
/* eslint-disable @typescript-eslint/no-require-imports, no-undef */
const glob = require("glob");
const { nextJsOrgRewriteConfig } = require("./getNextjsOrgRewriteConfig");

// Top-level route names that are explicitly allowed for org rewrite (whitelist)

const topLevelRouteNamesWhitelistedForRewrite = exports.topLevelRouteNamesWhitelistedForRewrite = [
  // We don't allow all dashboard route names to be used as slug because people are probably accustomed to access links like acme.cal.com/workflows, acme.cal.com/event-types etc.
  // So, we carefully allow, what is absolutely needed.
  // Allowed to be a team/user slug in organization because onboarding is a common team name
  'onboarding',
]

/**
 * Extracts top-level route names from all pages/app files and excludes them from org rewrite.
 * For example: /abc/def/ghi -> 'abc'
 * 
 * These top-level route names are excluded from rewrites in beforeFiles in next.config.js
 * to prevent conflicts with organization slug rewrites.
 */
/* eslint-disable no-undef */
let topLevelRoutesExcludedFromOrgRewrite = exports.topLevelRoutesExcludedFromOrgRewrite = glob
  .sync(
    "{pages,app,app/(booking-page-wrapper),app/(use-page-wrapper),app/(use-page-wrapper)/(main-nav)}/**/[^_]*.{tsx,js,ts}",
    {
      cwd: __dirname,
    }
  )
  .map((filename) =>
    filename
      // Remove the directory prefix (pages/, app/ and route group folders.)
      .replace(
        /^(app\/\(use-page-wrapper\)\/\(main-nav\)|app\/\(use-page-wrapper\)|app\/\(booking-page-wrapper\)|pages|app)\//,
        ""
      )
      // Remove file extensions
      .replace(/(\.tsx|\.js|\.ts)/, "")
      // Extract only the top-level route name (e.g., /abc/def -> abc)
      .replace(/\/.*/, "")
  )
  .filter(
    (v, i, self) =>
      self.indexOf(v) === i &&
      ![
        "[user]",
        "_trpc",
        "layout",
        "layoutHOC",
        "WithAppDirSsg",
        "global-error",
        "WithAppDirSsr",
        "WithEmbedSSR",
        "WithEmbedSSR.test",
        "ShellMainAppDir",
        "ShellMainAppDirBackButton",
      ].some((prefix) => v.startsWith(prefix))
  )
  .filter((page) => {
    return !topLevelRouteNamesWhitelistedForRewrite.includes(page);
  });

// .* matches / as well(Note: *(i.e wildcard) doesn't match / but .*(i.e. RegExp) does)
// It would match /free/30min but not /bookings/upcoming because 'bookings' is an item in pages
// It would also not match /free/30min/embed because we are ensuring just two slashes
// ?!book ensures it doesn't match /free/book page which doesn't have a corresponding new-booker page.
// [^/]+ makes the RegExp match the full path, it seems like a partial match doesn't work.
// book$ ensures that only /book is excluded from rewrite(which is at the end always) and not /booked
/* eslint-disable no-undef */
exports.nextJsOrgRewriteConfig = nextJsOrgRewriteConfig;

/**
 * Returns a regex that matches all existing routes, virtual routes (like /forms, /router, /success etc) and nextjs special paths (_next, public)
 * @param {string} suffix - The suffix to append to each route in the regex
 */
function getRegExpMatchingAllReservedRoutes(suffix) {
  // Following routes don't exist but they work by doing rewrite. Thus they need to be excluded from matching the orgRewrite patterns
  // Make sure to keep it upto date as more nonExistingRouteRewrites are added.
  const otherNonExistingRoutePrefixes = ["forms", "router", "success", "cancel"];

  // Most files/dirs in public dir must not be rewritten to org pages. Ideally it should be all the content of public dir, but that can be done later
  // It is important to exclude the embed pages separately here because with SINGLE_ORG_SLUG enabled, the entire domain is eligible for rewrite vs just the org subdomain otherwise
  const staticAssets = ["embed"];

  // FIXME: I am not sure why public is needed here, an asset 'test' in public isn't accessible through "/public/test" but only through "/test"
  // We should infact scan through all files in public and exclude them instead.
  const nextJsSpecialPaths = ["_next", "public"];

  let allTopLevelRoutesExcludedFromOrgRewrite = topLevelRoutesExcludedFromOrgRewrite
    .concat(otherNonExistingRoutePrefixes)
    .concat(nextJsSpecialPaths)
    .concat(staticAssets);
  return allTopLevelRoutesExcludedFromOrgRewrite.join(`${suffix}|`) + suffix;
}

// To handle /something
exports.orgUserRoutePath = `/:user((?!${getRegExpMatchingAllReservedRoutes("/?$")})[a-zA-Z0-9\-_]+)`;

// To handle /something/somethingelse
exports.orgUserTypeRoutePath = `/:user((?!${getRegExpMatchingAllReservedRoutes(
  "/"
)})[^/]+)/:type((?!avatar\.png)[^/]+)`;

// To handle /something/somethingelse/embed
exports.orgUserTypeEmbedRoutePath = `/:user((?!${getRegExpMatchingAllReservedRoutes("/")})[^/]+)/:type/embed`;
